/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package MNetSockets.DataChanel;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.LinkedList;
import java.util.Queue;
import net.sf.json.JSONObject;

/**
 *
 * @author wcss
 */
public class DataClient implements Runnable {

    private DatagramSocket ds;
    private byte[] recbuf = null;
    private DatagramPacket rec = null;
    private Thread tt  =null;
    private int port;
    public IUDPDataReader receiveEvent;
    public Boolean isRun;
    public Queue<QueueObject> queue = new LinkedList<QueueObject>();
    private Thread ttShell = null;
    public final static String udpDataEndFlag = "###";
    
    /**
     * 投递消息
     * @param address
     * @param data 
     */
    public void handleUDPDataRead(SocketAddress address,Object data)
    {
        if (this.receiveEvent != null)
        {
            this.receiveEvent.dataRead(this,address,data);
        }
    }

    /**
     * 构造函数
     * @param port 
     */
    public DataClient(int port)
    {
        this.port = port;
        recbuf = new byte[1024];
        rec = new DatagramPacket(recbuf, recbuf.length);
        isRun = false;
    }

    /**
     * 初始化
     * @throws Exception 
     */
    public void init() throws Exception {
        if (port < 1024 || port > 655535) {
            ds = new DatagramSocket();
        } else {
            ds = new DatagramSocket(port);
        }
    }

    /**
     * 开始监听线程
     * @throws Exception 
     */
    public void start() throws Exception {
        System.out.println("start");
        System.out.println("LocalPort:" + port);
        init();
        isRun = true;
        tt = new Thread(this);
        tt.setDaemon(true);
        tt.start();// recive thread
        
        ttShell = new Thread(new UDPDataRun(this));
        ttShell.setDaemon(true);
        ttShell.start();
    }

    /**
     * 停止监听线程
     */
    public void stop()
    {
        isRun = false;
        if (ds != null)
        {
            ds.close();
        }
    }
    
    /**
     * 发送消息(字符串)
     * @param addr 地址
     * @param cmd 字符串
     * @return 正在发送的包
     * @throws Exception 
     */
    public DatagramPacket send(SocketAddress addr,String cmd) throws Exception 
    {
        System.out.println("Send_UDP_Msg: " + cmd);
        return sendBytes(addr, (cmd + DataClient.udpDataEndFlag).getBytes());
    }

    /**
     * 发送数据(JSON文本)
     * @param addr 地址
     * @param jsonobj JSON对象
     * @return 正在发送的包
     * @throws Exception 
     */
    public DatagramPacket sendWithJSON(SocketAddress addr,Object jsonobj) throws Exception
    {
        return send(addr,JSONObject.fromObject(jsonobj).toString());
    }
    
    /**
     * 发送数据（字节数组）
     * @param addr 地址
     * @param data 字节数组
     * @return
     * @throws Exception 
     */
    private DatagramPacket sendBytes(SocketAddress addr, byte[] data) throws Exception
    {
        System.out.println("Send_UDP_Msg_To:" + addr);
        if (data.length <= recbuf.length)
        {
           DatagramPacket pack = new DatagramPacket(data, data.length, addr);
           ds.send(pack);
           return pack;
        }else
        {
            throw new Exception("data package size is " + recbuf.length + " only!");
        }
    }

    /**
     * 运行体
     */
    public void run() 
    {
        while(isRun)
        {
            try {
                ds.receive(rec);
                String msg = new String(rec.getData(), rec.getOffset(), rec.getLength());
                if (msg.trim().endsWith(DataClient.udpDataEndFlag))
                {
                   this.queue.offer(new QueueObject(rec.getSocketAddress(),msg));
                }else
                {
                    System.out.println("收到来自" + rec.getSocketAddress() + "的无效数据！内容：" + msg);
                }
            } catch (Exception e) {
                e.printStackTrace();
                break;
            }
        }
    }

}
